#include "slidegenerator.h"
#include "slidepaintbox.h"

SlideGenerator::SlideGenerator(SqliteDbWrapper& db)
{
    m_outputDevice = NULL;
    m_dataBase = &db;    
    m_viewer = new EmbeddedSvgViewer();
}

SlideGenerator::SlideGenerator(SqliteDbWrapper& db, QFile& device)
{
    m_outputDevice = &device;
    m_dataBase = &db;
    m_viewer = new EmbeddedSvgViewer();
}

void SlideGenerator::LoadNewTemplate(const char* inputTemplatePath)
{
    QFile inputTemplateFile(QString::fromAscii(inputTemplatePath));

    std::cout << "Reading Template \'" << inputTemplatePath << "\'...";

    if (inputTemplateFile.open(QIODevice::ReadOnly) && inputTemplateFile.isReadable()){
        m_slideModel.CacheContentsFromFile(inputTemplateFile);
        inputTemplateFile.close();
    } else {
        std::cout << "Template cannot be read!\n";
    }

}

void SlideGenerator::FetchNewRoute(const char* route)
{
    std::string sql;
    sql = m_routeId = route;


    std::cout << "Querying route number " << sql << "\n...";

    sql.insert(0, "SELECT Stop.StopName, LineStop.\'Order\', \
                       Stop.StartSecondaryLine, Stop.SecondaryLineText, \
                       StopCorresp.Correspondance \
                       FROM LineStop, Stop, StopCorresp \
                       WHERE LineStop.LineID=\"" );

    sql.append("\" AND Stop.StopID=LineStop.StopID \
                        AND Stop.StopID=StopCorresp.StopID \
                        ORDER BY LineStop.\'Order\' ASC;"
                       );

    std::cout << "Query returned " << m_dataBase->QueryStops(sql.c_str()) << " stops\n";

    m_focalStop = m_dataBase->StopVector.begin();
}

// SelectFocalStop methods are more test-oriented, HTC software will
// push the current stop symbol in reality

void SlideGenerator::SelectFocalStop(StopItr& focalStopIterator){

    m_focalStop = focalStopIterator;

}

void SlideGenerator::SelectFocalStop(std::string focalStopName){

    //TODO: Iterative search by stopName

}

void SlideGenerator::SelectFocalStop(int focalStopPosition){

    if (focalStopPosition > (signed)m_dataBase->StopVector.size())
        focalStopPosition = m_dataBase->StopVector.size();
    if (focalStopPosition < 1) focalStopPosition = 1;

    m_focalStop = m_dataBase->StopVector.begin();

    for (int i = 1; i < focalStopPosition; i++){
        m_focalStop++;
    }
}

void SlideGenerator::GenerateSlide(){

    //Database and input template must be valid before an output slide can be generated
    //TODO: Make this condition more verbose
    if( m_slideModel.InitialiseOutputDocument(m_dataBase->GetStyleSheet(m_routeId.c_str()).c_str()) && (signed)m_dataBase->StopVector.size() > 0){
        generateDynamicContent();
        m_slideModel.FinaliseOutputDocument();
        std::cout << "Exporting model...";
        exportSlideModel();
        std::cout << "Exported\n";
    }
}

/////////////////////
///Private Methods///
/////////////////////

void SlideGenerator::exportSlideModel(void){

    if (m_outputDevice != NULL){    //Output file handle is left null if the appropriate
                                    //constructor is not called at start-up

        m_outputDevice->open(QIODevice::WriteOnly);

        QTextStream ts(m_outputDevice);
        ts.setCodec("UTF-8");

        ts << m_slideModel.GetOutputDocAsByteArray();

        m_outputDevice->close();
        m_viewer->NewSlideFromFile(m_outputDevice->fileName());

    } else {        
        m_viewer->NewSlideFromByteArray(m_slideModel.GetOutputDocAsByteArray());
    }

}

void SlideGenerator::generateDynamicContent(){

    //Iterate through all dynamic tags that are assigned to the root node and use them to call
    //the appropriate generation procedure
    for (TupleItr tp = m_slideModel.GetFirstTupleWithParent(m_slideModel.GetRootTuple());
         tp != m_slideModel.GetNullTuple();
         tp = m_slideModel.GetNextSiblingForTuple(tp))
    {
        if (tp->self.toElement().tagName().toAscii() == "lineplan")
            SlidePaintBox::PaintLinePlan(tp, m_slideModel, m_dataBase->StopVector, m_focalStop);
        else if (tp->self.toElement().tagName().toAscii() == "multitext")
            SlidePaintBox::PaintMultiText(tp, m_slideModel, m_dataBase->StopVector, m_focalStop, m_routeId);
        else if (tp->self.toElement().tagName().toAscii() == "graphic")
            SlidePaintBox::PaintGraphicsFrame(tp, m_slideModel, m_dataBase->StopVector, m_focalStop);
        else continue;
    }
}

SlideGenerator::~SlideGenerator(){

    delete m_dataBase;
    delete m_outputDevice;
    delete m_viewer;

}
